// 装饰器模式
package main

import "fmt"

// ===== 抽象层 ============================================================

type Phone interface {
	Show()
}

// Decorator 抽象的装饰器，装饰器的基础类
// （该类本应该是interface，但是Golang的interface语法不可以有成员属性）
// 把下面这个类比成:
//
//	type Decorator interface {
//	    phone Phone
//	}
type Decorator struct {
	phone Phone // 组合进来抽象的phone
}

// ===== 实现层 ============================================================

// 具体的构件--------------------------------------------------------

type Huawei struct{}

func (hw *Huawei) Show() {
	fmt.Println("秀出了华为手机")
}

type Xiaomi struct{}

func (xh *Xiaomi) Show() {
	fmt.Println("秀出了小米手机")
}

// 具体的装饰器--------------------------------------------------------

// MoDecorator 贴膜装饰器++++++++++++++++++++++++
type MoDecorator struct {
	//decorator *Decorator  // 指针嵌套结构体
	Decorator // 匿名嵌套结构体 继承基础的装饰器类
}

func (md *MoDecorator) Show() {
	//md.decorator.phone.Show()
	md.phone.Show()
	fmt.Println("贴膜的手机") // 装饰器额外装饰的功能
}

func NewMoDecorator(phone Phone) Phone {
	return &MoDecorator{Decorator{phone: phone}}
}

// KeDecorator 外壳装饰器++++++++++++++++++++++++
type KeDecorator struct {
	//decorator *Decorator  // 指针嵌套结构体
	Decorator // 匿名嵌套结构体 继承基础的装饰器类
}

func (kd *KeDecorator) Show() {
	//md.decorator.phone.Show()
	kd.phone.Show()
	fmt.Println("套壳的手机") // 装饰器额外装饰的功能
}

func NewKeDecorator(phone Phone) Phone {
	return &KeDecorator{Decorator{phone: phone}}
}

// ===== 业务逻辑层 ============================================================

func main() {
	var huawei Phone
	huawei = &Huawei{}
	huawei.Show()

	fmt.Println("-------------------")

	var moHuawei Phone
	moHuawei = NewMoDecorator(huawei)
	moHuawei.Show()

	fmt.Println("-------------------")

	var keHuawei Phone
	keHuawei = NewKeDecorator(huawei)
	keHuawei.Show()

	fmt.Println("-------------------")

	var moKeHuawei Phone
	moKeHuawei = NewMoDecorator(keHuawei)
	moKeHuawei.Show()
}
